#pragma once


#include"proto.h"
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<pthread.h>
#include<stdlib.h>
#include<iostream>


namespace TServer
{
  class TcpServer
  {
    private:
      int port;
      int listen_sock;
    public:
      TcpServer(char* _port):port(atoi(_port)),listen_sock(-1)
      {}
      void Init()
      {
        listen_sock=socket(AF_INET,SOCK_STREAM,0);
        if(listen_sock<0)
        {
          exit(-1);
        }
        struct sockaddr_in local;
        local.sin_family=AF_INET;
        local.sin_port=htons(port);
        local.sin_addr.s_addr=INADDR_ANY;
        if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0)
        {
          exit(-2);
        }
        if(listen(listen_sock,5)<0)
        {
          exit(-3);
        }
      }
      static void* Routine(void* s)
      {
        int sock=*((int*)s);
        delete (int*)s;
        Pra::Data data;
        recv(sock,&data,sizeof(data),0);
        int x=data.x;
        int y=data.y;
        Pra::Result res;
        switch(data.op)
        {
          case '+':
            res.result=x+y;
            break;
          case '-':
            res.result=x-y;
            break;
          case '*':
            res.result=x*y;
            break;
          case '/':
            if(y==0)
            {
              res.code=-1;
              break;
            }
            res.result=x/y;
            break;
          case '%':
            if(y==0)
            {
              res.code=-2;
              break;
            }
            res.result=x%y;
            break;
          default:
            res.code=-3;
            break;
        }
        send(sock,&res,sizeof(res),0);
        close(sock);
        return nullptr;
      }
      void Loop()
      {
        while(true)
        {
          int sock;
          struct sockaddr peer;
          socklen_t len=sizeof(peer);
          sock=accept(listen_sock,(struct sockaddr*)&peer,&len);
          if(sock>0)
          {
            int* sk=new int(sock);
            pthread_t pid;
            pthread_create(&pid,nullptr,Routine,sk);
          }
          else{
            continue;
          }
        }
      }

      ~TcpServer()
      {
        if(listen_sock>0) close(listen_sock);
      }
  };
}
